package com.ruben;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ruben.enumeration.GenderEnum;
import com.ruben.pojo.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @ClassName: FastJsonDemo
 * @Description:
 * @Date: 2020/8/13 20:00
 * *
 * @author: achao<achao1441470436 @ gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
public class FastJsonDemo {

    public static void main(String[] args) {

    }

    private static void fastJsonDemo() {
        Instant from = LocalDateTime.parse("2021-01-09 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)).toInstant(ZoneOffset.MAX);

        Student supa = Student.builder().name("supa").age(20).gender(GenderEnum.MALE).birthday(Date.from(from)).json("{\"word\":\"xxx\"}").build();
        String serializeStr = JSON.toJSONString(supa);
        System.out.println(serializeStr);

        Student student = JSON.parseObject(serializeStr, Student.class);
        System.out.println(student);
    }

    private static void jsonConvert() {
        Map<String, Object> map = new HashMap<>(1 << 3);
        map.put("data", "操作成功！");
        map.put("code", 200);
        map.put("success", true);
        map.put("list", Arrays.asList("你好", "加油"));
        map.put("userList", Arrays.asList(new User("ruben", "achao")));
        String jsonString = JSON.toJSONString(map);
        System.out.println(jsonString);
        JSONObject jsonObject = JSON.parseObject(jsonString);
        //String
        String data = jsonObject.getString("data");
        System.out.println(data);
        //int
        int code = jsonObject.getIntValue("code");
        System.out.println(code);
        //boolean
        boolean success = jsonObject.getBooleanValue("success");
        System.out.println(success);
        //list
        JSONArray list = jsonObject.getJSONArray("list");
        list.forEach(System.out::println);

        Map jsonToMap = JSON.parseObject(jsonString, Map.class);
        System.out.println(jsonToMap.get("code"));

        String userListString = jsonObject.getString("userList");
        List<User> userList = JSON.parseArray(userListString, User.class);
        userList.forEach(System.out::println);
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Student implements Serializable {
        private static final long serialVersionUID = -3289647584974663707L;
        @JSONField(ordinal = 3, name = "studentName", alternateNames = {"myName", "name", "studentName"})
        private String name;
        @JSONField(ordinal = 1, serialize = false)
        private Integer age;
        @JSONField(serialzeFeatures = {SerializerFeature.WriteNullStringAsEmpty})
        private String job;
        @JSONField(ordinal = 2, serializeUsing = GenderEnumParser.class, deserializeUsing = GenderEnumFormatter.class)
        private GenderEnum gender;
        @JSONField(format = "yyyy年MM月dd日E", deserialize = false)
        private Date birthday;
        @JSONField(jsonDirect = true)
        private String json;
    }

    /**
     * 性别序列化
     */
    public static class GenderEnumParser implements ObjectSerializer {
        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
            Integer genderCode = null;
            if (fieldType.getTypeName().equals(GenderEnum.class.getName())) {
                genderCode = ((GenderEnum) object).getCode();
            }
            serializer.write(genderCode);
        }
    }

    public static class GenderEnumFormatter implements ObjectDeserializer {
        @Override
        public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
            JSONObject jsonObject = JSON.parseObject(parser.getInput());
            Integer genderCode = jsonObject.getInteger(String.valueOf(fieldName));
            return (T) Arrays.stream(GenderEnum.values()).filter(gender -> gender.getCode().equals(genderCode)).findFirst().orElse(null);
        }

        @Override
        public int getFastMatchToken() {
            return 0;
        }
    }
}
